package com.coai.manufacturing.service

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.springframework.kafka.core.KafkaTemplate
import org.springframework.stereotype.Service
import java.time.LocalDateTime

/**
 * 智能制造服务
 * 
 * 提供智能制造的核心功能：
 * - 生产调度优化（基于优先级和资源分配）
 * - 预测性维护（基于设备数据）
 * - 质量预测（基于工艺参数）
 * 
 * @property kafkaTemplate Kafka消息发送模板
 */
@Service
class ManufacturingService(
    private val kafkaTemplate: KafkaTemplate<String, Any>
) {
    
    /**
     * AI生产调度优化
     */
    /**
     * 生产调度优化
     * 
     * 使用AI算法优化生产任务排程，提高设备利用率
     * 考虑因素：交期、优先级、设备产能、切换成本
     * 
     * @param orders 待调度的生产订单列表
     * @return 优化后的生产计划
     */
    suspend fun optimizeProductionSchedule(
        orders: List<ProductionOrderInfo>
    ): ProductionSchedule = withContext(Dispatchers.IO) {
        
        // AI调度优化（优先级排序 + 资源分配）
        try {
            // 1. 按优先级和截止日期排序
            val sortedOrders = orders.sortedWith(
                compareBy<ProductionOrderInfo> { it.deadline }
                    .thenBy { it.quantity }
            )
            
            // 2. 模拟设备资源
            val equipmentList = listOf("EQ-001", "EQ-002", "EQ-003")
            val equipmentSchedule = mutableMapOf<String, MutableList<ScheduledTask>>()
            equipmentList.forEach { equipmentSchedule[it] = mutableListOf() }
            
            val schedule = mutableListOf<ScheduledTask>()
            var currentTime = LocalDateTime.now()
            
            // 3. 分配任务到设备
            sortedOrders.forEachIndexed { idx, order ->
                // 找到最早可用的设备
                val equipment = equipmentList.minByOrNull { eqId ->
                    equipmentSchedule[eqId]?.lastOrNull()?.endTime ?: currentTime
                } ?: equipmentList[0]
                
                val lastTask = equipmentSchedule[equipment]?.lastOrNull()
                val startTime = lastTask?.endTime ?: currentTime
                
                // 估算加工时间（每件产品需要2分钟）
                val processingMinutes = (order.quantity * 2).toLong()
                val endTime = startTime.plusMinutes(processingMinutes)
                
                val task = ScheduledTask(
                    orderId = order.orderId,
                    equipmentId = equipment,
                    startTime = startTime,
                    endTime = endTime,
                    priority = idx + 1
                )
                
                schedule.add(task)
                equipmentSchedule[equipment]?.add(task)
            }
            
            // 4. 计算利用率
            val totalTime = schedule.maxOfOrNull { it.endTime.hour - currentTime.hour } ?: 8
            val workingHours = 8 // 每天工作8小时
            val utilizationRate = (totalTime.toDouble() / workingHours).coerceAtMost(1.0)
            
            ProductionSchedule(
                tasks = schedule,
                utilizationRate = utilizationRate,
                totalMakespan = totalTime
            )
        } catch (e: Exception) {
            // 失败时返回默认调度
            val schedule = orders.mapIndexed { idx, order ->
                ScheduledTask(
                    orderId = order.orderId,
                    equipmentId = "EQ-001",
                    startTime = LocalDateTime.now().plusHours(idx.toLong()),
                    endTime = LocalDateTime.now().plusHours(idx + 1L),
                    priority = idx + 1
                )
            }
            
            ProductionSchedule(
                tasks = schedule,
                utilizationRate = 0.85,
                totalMakespan = orders.size
            )
        }
    }
    
    /**
     * AI预测性维护
     */
    /**
     * 预测性维护
     * 
     * 基于设备运行数据预测故障风险，提前安排维护
     * 分析数据：振动、温度、电流、运行时长等
     * 
     * @param equipmentId 设备ID
     * @return 维护预测结果
     */
    suspend fun predictMaintenance(equipmentId: String): MaintenancePrediction = withContext(Dispatchers.IO) {
        
        // 基于设备数据的故障预测
        try {
            // TODO: 实际应该基于设备传感器数据（振动、温度、电流等）
            // 使用机器学习模型进行预测
            
            // 模拟预测逻辑
            val equipmentAge = equipmentId.hashCode().rem(365) // 模拟设备使用天数
            val risk = when {
                equipmentAge > 300 -> "HIGH"
                equipmentAge > 150 -> "MEDIUM"
                else -> "LOW"
            }
            
            val daysUntilFailure = when (risk) {
                "HIGH" -> 7L
                "MEDIUM" -> 15L
                else -> 30L
            }
            
            val confidence = when (risk) {
                "HIGH" -> 0.85
                "MEDIUM" -> 0.78
                else -> 0.65
            }
            
            val recommendation = when (risk) {
                "HIGH" -> "建议立即进行预防性维护，更换易损件"
                "MEDIUM" -> "建议在未来${daysUntilFailure}天内进行预防性维护"
                else -> "设备运行正常，继续监控"
            }
            
            MaintenancePrediction(
                equipmentId = equipmentId,
                predictedFailureDate = LocalDateTime.now().plusDays(daysUntilFailure),
                confidence = confidence,
                recommendedAction = recommendation,
                riskLevel = risk
            )
        } catch (e: Exception) {
            MaintenancePrediction(
                equipmentId = equipmentId,
                predictedFailureDate = LocalDateTime.now().plusDays(30),
                confidence = 0.5,
                recommendedAction = "预测失败，请手动检查",
                riskLevel = "UNKNOWN"
            )
        }
    }
    
    /**
     * AI质量预测
     */
    /**
     * 质量预测
     * 
     * 基于工艺参数预测产品质量，提前发现潜在问题
     * 分析参数：温度、压力、速度、湿度等
     * 
     * @param productionOrderId 生产订单ID
     * @param processParameters 工艺参数集合
     * @return 质量预测结果
     */
    suspend fun predictQuality(
        productionOrderId: String,
        processParameters: Map<String, Double>
    ): QualityPrediction = withContext(Dispatchers.IO) {
        
        // 基于工艺参数预测质量
        try {
            // TODO: 实际应该使用训练好的机器学习模型
            
            // 1. 提取关键工艺参数
            val temperature = processParameters["temperature"] ?: 0.0
            val pressure = processParameters["pressure"] ?: 0.0
            val speed = processParameters["speed"] ?: 0.0
            val humidity = processParameters["humidity"] ?: 0.0
            
            // 2. 定义最优参数范围
            val optimalRanges = mapOf(
                "temperature" to (180.0 to 220.0),
                "pressure" to (5.0 to 8.0),
                "speed" to (50.0 to 100.0),
                "humidity" to (40.0 to 60.0)
            )
            
            // 3. 计算参数偏离度
            val deviations = mutableMapOf<String, Double>()
            val keyFactors = mutableListOf<String>()
            
            // 温度偏离
            val tempRange = optimalRanges["temperature"]!!
            if (temperature < tempRange.first || temperature > tempRange.second) {
                val deviation = if (temperature < tempRange.first) {
                    (tempRange.first - temperature) / tempRange.first
                } else {
                    (temperature - tempRange.second) / tempRange.second
                }
                deviations["temperature"] = deviation
                if (deviation > 0.1) keyFactors.add("温度")
            }
            
            // 压力偏离
            val pressRange = optimalRanges["pressure"]!!
            if (pressure < pressRange.first || pressure > pressRange.second) {
                val deviation = if (pressure < pressRange.first) {
                    (pressRange.first - pressure) / pressRange.first
                } else {
                    (pressure - pressRange.second) / pressRange.second
                }
                deviations["pressure"] = deviation
                if (deviation > 0.1) keyFactors.add("压力")
            }
            
            // 速度偏离
            val speedRange = optimalRanges["speed"]!!
            if (speed < speedRange.first || speed > speedRange.second) {
                val deviation = if (speed < speedRange.first) {
                    (speedRange.first - speed) / speedRange.first
                } else {
                    (speed - speedRange.second) / speedRange.second
                }
                deviations["speed"] = deviation
                if (deviation > 0.1) keyFactors.add("速度")
            }
            
            // 4. 计算预测次品率
            val avgDeviation = if (deviations.isEmpty()) 0.0 else deviations.values.average()
            val baseDefectRate = 0.01 // 基础次品率 1%
            val predictedDefectRate = (baseDefectRate * (1 + avgDeviation * 5)).coerceAtMost(0.2)
            
            // 5. 计算质量分数
            val qualityScore = (1.0 - predictedDefectRate).coerceIn(0.0, 1.0)
            
            // 6. 补充关键因素
            if (keyFactors.isEmpty()) {
                keyFactors.add("工艺参数正常")
            }
            
            QualityPrediction(
                orderId = productionOrderId,
                predictedDefectRate = predictedDefectRate,
                qualityScore = qualityScore,
                keyFactors = keyFactors
            )
        } catch (e: Exception) {
            logger.error("Failed to predict quality", e)
            QualityPrediction(
                orderId = productionOrderId,
                predictedDefectRate = 0.05,
                qualityScore = 0.95,
                keyFactors = listOf("预测失败")
            )
        }
    }
}

data class ProductionOrderInfo(
    val orderId: String,
    val productId: String,
    val quantity: Int,
    val deadline: LocalDateTime
)

data class ProductionSchedule(
    val tasks: List<ScheduledTask>,
    val utilizationRate: Double,
    val totalMakespan: Int
)

data class ScheduledTask(
    val orderId: String,
    val equipmentId: String,
    val startTime: LocalDateTime,
    val endTime: LocalDateTime,
    val priority: Int
)

data class MaintenancePrediction(
    val equipmentId: String,
    val predictedFailureDate: LocalDateTime,
    val confidence: Double,
    val recommendedAction: String,
    val riskLevel: String
)

data class QualityPrediction(
    val orderId: String,
    val predictedDefectRate: Double,
    val qualityScore: Double,
    val keyFactors: List<String>
)
